/* tinyplay.c
**
** Copyright 2011, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**     * Redistributions of source code must retain the above copyright
**       notice, this list of conditions and the following disclaimer.
**     * Redistributions in binary form must reproduce the above copyright
**       notice, this list of conditions and the following disclaimer in the
**       documentation and/or other materials provided with the distribution.
**     * Neither the name of The Android Open Source Project nor the names of
**       its contributors may be used to endorse or promote products derived
**       from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
** DAMAGE.
*/

#include <tinyalsa/asoundlib.h>
#include "tinyplay.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//#include "media/AudioTrack.h"
#include "include/Log.h"
#include "audioutils/resampler.h"
#include "AudioChannelObserver.h"
#include "xq_player.h"
#include <sys/system_properties.h>

#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
#define ID_FMT  0x20746d66
#define ID_DATA 0x61746164

#define PROPERTY_VALUE_MAX 92
static char board_platform[PROPERTY_VALUE_MAX] = { 0 };
static char bluetooth_call[PROPERTY_VALUE_MAX] = { 0 };
static char dump_tinyplay[PROPERTY_VALUE_MAX] = { 0 };

static struct resampler_itfe *nice_resampler;

FunctionMicrophoneCallBack mMicrophoneCallback = NULL;

void setMircophoneCallBack(FunctionMicrophoneCallBack callback)
{
	mMicrophoneCallback = callback;
}

int tinyplayAudioType = 0;
int inputChannels = 1;
int inputSampleRate = 16000;
int inputBits = 16;

volatile struct pcm *mic_pcm = NULL;
int tinyplaySave = 0;
volatile int mt8163_platform = 0;
volatile int mt8163_bluetooth_call = 0;
volatile int mic_capturing = 1;
pthread_t	 micAudioThread;          // Thread to offload sending audio data.
pthread_t *	 micAudioThreadPtr;       // Ptr to sendAudioThread when valid.

#if 0
struct riff_wave_header {
    uint32_t riff_id;
    uint32_t riff_sz;
    uint32_t wave_id;
};

struct chunk_header {
    uint32_t id;
    uint32_t sz;
};

struct chunk_fmt {
    uint16_t audio_format;
    uint16_t num_channels;
    uint32_t sample_rate;
    uint32_t byte_rate;
    uint16_t block_align;
    uint16_t bits_per_sample;
};

static int close = 0;

void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
                 unsigned int rate, unsigned int bits, unsigned int period_size,
                 unsigned int period_count, uint32_t data_sz);

void stream_close(int sig)
{
    /* allow the stream to be closed gracefully */
    signal(sig, SIG_IGN);
    close = 1;
}

int main_test(int argc, char **argv)
{
    FILE *file;
    struct riff_wave_header riff_wave_header;
    struct chunk_header chunk_header;
    struct chunk_fmt chunk_fmt;
    unsigned int device = 0;
    unsigned int card = 0;
    unsigned int period_size = 1024;
    unsigned int period_count = 4;
    char *filename;
    int more_chunks = 1;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]"
                " [-n n_periods] \n", argv[0]);
        return 1;
    }

    filename = argv[1];
    file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Unable to open file '%s'\n", filename);
        return 1;
    }

    fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
    if ((riff_wave_header.riff_id != ID_RIFF) ||
        (riff_wave_header.wave_id != ID_WAVE)) {
        fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
        fclose(file);
        return 1;
    }

    do {
        fread(&chunk_header, sizeof(chunk_header), 1, file);

        switch (chunk_header.id) {
        case ID_FMT:
            fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
            /* If the format header is larger, skip the rest */
            if (chunk_header.sz > sizeof(chunk_fmt))
                fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
            break;
        case ID_DATA:
            /* Stop looking for chunks */
            more_chunks = 0;
            chunk_header.sz = le32toh(chunk_header.sz);
            break;
        default:
            /* Unknown chunk, skip bytes */
            fseek(file, chunk_header.sz, SEEK_CUR);
        }
    } while (more_chunks);

    /* parse command line arguments */
    argv += 2;
    while (*argv) {
        if (strcmp(*argv, "-d") == 0) {
            argv++;
            if (*argv)
                device = atoi(*argv);
        }
        if (strcmp(*argv, "-p") == 0) {
            argv++;
            if (*argv)
                period_size = atoi(*argv);
        }
        if (strcmp(*argv, "-n") == 0) {
            argv++;
            if (*argv)
                period_count = atoi(*argv);
        }
        if (strcmp(*argv, "-D") == 0) {
            argv++;
            if (*argv)
                card = atoi(*argv);
        }
        if (*argv)
            argv++;
    }

    play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
                chunk_fmt.bits_per_sample, period_size, period_count, chunk_header.sz);

    fclose(file);

    return 0;
}

int check_param(struct pcm_params *params, unsigned int param, unsigned int value,
                 char *param_name, char *param_unit)
{
    unsigned int min;
    unsigned int max;
    int is_within_bounds = 1;

    min = pcm_params_get_min(params, param);
    if (value < min) {
        fprintf(stderr, "%s is %u%s, device only supports >= %u%s\n", param_name, value,
                param_unit, min, param_unit);
        is_within_bounds = 0;
    }

    max = pcm_params_get_max(params, param);
    if (value > max) {
        fprintf(stderr, "%s is %u%s, device only supports <= %u%s\n", param_name, value,
                param_unit, max, param_unit);
        is_within_bounds = 0;
    }

    return is_within_bounds;
}

int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels,
                        unsigned int rate, unsigned int bits, unsigned int period_size,
                        unsigned int period_count)
{
    struct pcm_params *params;
    int can_play;

    params = pcm_params_get(card, device, PCM_OUT);
    if (params == NULL) {
        fprintf(stderr, "Unable to open PCM device %u.\n", device);
        return 0;
    }

    can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz");
    can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels");
    can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitwidth", " bits");
    can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", " frames");
    can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", " periods");

    pcm_params_free(params);

    return can_play;
}

void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
                 unsigned int rate, unsigned int bits, unsigned int period_size,
                 unsigned int period_count, uint32_t data_sz)
{
    struct pcm_config config;
    struct pcm *pcm;
    char *buffer;
    unsigned int size, read_sz;
    int num_read;

    memset(&config, 0, sizeof(config));
    config.channels = channels;
    config.rate = rate;
    config.period_size = period_size;
    config.period_count = period_count;
    if (bits == 32)
        config.format = PCM_FORMAT_S32_LE;
    else if (bits == 24)
        config.format = PCM_FORMAT_S24_3LE;
    else if (bits == 16)
        config.format = PCM_FORMAT_S16_LE;
    config.start_threshold = 0;
    config.stop_threshold = 0;
    config.silence_threshold = 0;

    if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) {
        return;
    }

    pcm = pcm_open(card, device, PCM_OUT, &config);
    if (!pcm || !pcm_is_ready(pcm)) {
        fprintf(stderr, "Unable to open PCM device %u (%s)\n",
                device, pcm_get_error(pcm));
        return;
    }

    size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
    buffer = malloc(size);
    if (!buffer) {
        fprintf(stderr, "Unable to allocate %d bytes\n", size);
        free(buffer);
        pcm_close(pcm);
        return;
    }

    printf("Playing sample: %u ch, %u hz, %u bit %u bytes\n", channels, rate, bits, data_sz);

    /* catch ctrl-c to shutdown cleanly */
    signal(SIGINT, stream_close);

    do {
        read_sz = size < data_sz ? size : data_sz;
        num_read = fread(buffer, 1, read_sz, file);
        if (num_read > 0) {
            if (pcm_write(pcm, buffer, num_read)) {
                fprintf(stderr, "Error playing sample\n");
                break;
            }
            data_sz -= num_read;
        }
    } while (!close && num_read > 0 && data_sz > 0);

    free(buffer);
    pcm_close(pcm);
}
#endif

static struct pcm *init_pcm(unsigned int card, unsigned int device, unsigned int channels,
                 unsigned int rate, unsigned int bits, unsigned int period_size,
                 unsigned int period_count)
{
    struct pcm_config config;
    memset(&config, 0, sizeof(config));
    config.channels = channels;
    config.rate = rate;
    config.period_size = period_size;
    config.period_count = period_count;

	struct pcm *pcm;

    if (bits == 32)
        config.format = PCM_FORMAT_S32_LE;
    else if (bits == 24)
        config.format = PCM_FORMAT_S24_3LE;
    else if (bits == 16)
        config.format = PCM_FORMAT_S16_LE;
    config.start_threshold = 0;
    config.stop_threshold = 0;
    config.silence_threshold = 0;

    pcm = pcm_open(card, device, PCM_OUT, &config);
    if (!pcm || !pcm_is_ready(pcm)) {
        fprintf(stderr, "Unable to open PCM device %u (%s)\n",
                device, pcm_get_error(pcm));
        return NULL ;
    } else {
		fprintf(stderr, "open pcm successfully.......\n");
	}
    return pcm;
}

static int pcm_play(struct pcm *pcm, char *buffer, int data_sz, unsigned int size)
{
    unsigned int write_sz;
	char *pbuffer = buffer;
/* 	unsigned int size;
    size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); */
  do {
       write_sz = size < data_sz ? size : data_sz;
       if (pcm_write(pcm, pbuffer, write_sz)) {
                printf("Error playing sample\n");
                break;
            }
       data_sz -= write_sz;
	   pbuffer += write_sz;
    } while (data_sz > 0);

    return 0;
}


static int send_mic_data(char *buffer, unsigned int data_sz)
{
	char *pbuffer = NULL;
    unsigned int size, write_sz;
    unsigned int tsize;
	if( mic_pcm == NULL )
	{
		 LOGD("tinyplay microphone mic_pcm == NULL \n ");
	    unsigned int device = 1; //4G电话将device 改成0
	    unsigned int card = 1;
	    unsigned int period_size = 1024;
	    unsigned int period_count = 4;
	    unsigned int rate = 48000;

	    __system_property_get("ro.board.platform", board_platform);
	    __system_property_get("sys.lynx.bt.mt8163", bluetooth_call);
	    LOGD("microphone bluetooth_call = %s \n ", bluetooth_call);
	    if (strcmp(board_platform, "mt8163") == 0) {
	    	//mtk mt8163
	    	period_size = 960;
		    if (strcmp(bluetooth_call, "1") == 0) {
		    	mt8163_bluetooth_call = atoi(bluetooth_call);
		    	period_size = 320;
		    	rate = 16000;
		    }
	    }else {
		    char value4g  [ 20 ];
		    __system_property_get("lynx.rplay.4g", value4g);
		    if (strcmp(value4g, "1") == 0) {
		    	card = 0;
	//	    	period_size = 240; //3840 = period_size * period_count *channels * (format >> 3)
		    	period_size = data_sz / (period_count *2 * (16>>3));
		    	LOGD("microphone period_size = %d \n ", period_size);
		    }else{
		    	card = 1;
		    	period_size = 1024;
		    }
	    }

	    LOGD("microphone card = %d \n ", card);
	    LOGD("microphone period_size = %d \n ", period_size);
		unsigned int channels = 2;
		unsigned int bits = 16;
		mic_pcm = init_pcm(card, device, channels, rate, bits, period_size, period_count);
		if( mic_pcm !=NULL ){
			tsize = pcm_frames_to_bytes(mic_pcm, pcm_get_buffer_size(mic_pcm));
		}
	}
	if( mic_pcm != NULL )
	{
		pcm_play(mic_pcm, buffer, data_sz, tsize);
	}

    return 0;	
}

static uint64_t UpTicks(void) {
	uint64_t nanos;
	struct timespec ts;

	ts.tv_sec = 0;
	ts.tv_nsec = 0;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	nanos = ts.tv_sec;
	nanos *= 1000000000;
	nanos += ts.tv_nsec;
	return (nanos);
}

/*
	双转单
	参数1：资源buffer(双声道数据)
	参数2：资源buffer大小(单声道数据大小，注意：是buffer中音频数据帧数，而不是字节数)
	参数3：转换后buffer(单声道数据)
*/
void StereoToMono(const int16_t* src_audio,int frames,int16_t* dst_audio)
{
    for (int i = 0; i < frames; i++)
    {
    	//注意 >>1 只有在有符号整形的情况下才代表除以2
        dst_audio[i] =((int)src_audio[2 * i] + src_audio[2 * i + 1]) >> 1;
    }
}

/*
	单转双
	参数1：资源buffer(单声道数据)
	参数2：资源buffer大小(单声道数据大小，注意：是buffer中音频数据帧数，而不是字节数)
	参数3：转换后buffer(双声道数据)
*/
void MonoToStereo(const int16_t* src_audio,int frames,int16_t* dst_audio)
{
    for (int i = 0; i < frames; i++)
    {
        dst_audio[2 * i] = src_audio[i]; //left mic
        dst_audio[2 * i + 1] = src_audio[i]; //right mic
    }
}

static void *	_GeneralMicrophoneThread( void *inArg )
{
	LOGD("_GeneralMicrophoneThread run.\n ");
	FILE *file = NULL;
	if( tinyplaySave == 1 )
	{
//	    file = fopen("/data/microphone.pcm", "wb");
	    file = fopen("/sdcard/.debug/microphone.pcm", "wb");
	    if (!file) {
	        fprintf(stderr, "Unable to create file /data/microphone.pcm \n");
	    }
	}
	usleep(100*1000);
	mic_capturing = 1;
	int bits = 16;
	int delay_ms = 32;// 20ms  LatencyMs 32
	int rate = inputSampleRate; //sampleRate
	int channels = inputChannels;
	int buf_len = (rate * delay_ms / 1000) * (bits / 8 * channels);
	// 22360
	LOGD("microphone buf_len = %d \n ", buf_len);
	uint8_t mBuffer [buf_len];
	uint8_t* mock [buf_len];
	memset(mock,0,buf_len);

	int frames = buf_len / (bits / 8 * channels);

    ///add for box
    int16_t buffer_pcm[4096] = {0}; //48k mono buffer
    size_t bytes_size = 0;
    int16_t retlen;

    size_t in_frames = 0;
    size_t out_frames = 0;

    void *mAudioTrackHandle = xq_player_create(0, inputSampleRate, inputChannels, 16);
	while ( mic_capturing ) {
		if(mMicrophoneCallback != NULL )
		{
			//这里添加一个属性为同行者语音就绪状态
//			LOGD("txz tinyplay_loop microphone.");
			__system_property_set("sys.lynx.txz.channel", "1");

			mMicrophoneCallback(mBuffer,buf_len, frames, UpTicks());
			if(file != NULL && tinyplaySave == 1)
			{
				if (fwrite(mBuffer, sizeof(uint8_t), buf_len, file) != buf_len) {
					fprintf(stderr,"Error record microphone sample\n");
				}
			}
			xq_player_write(mAudioTrackHandle, mock,buf_len);

			if(mt8163_platform == 1 && mt8163_bluetooth_call == 1 )
			{
				//16k/24k  mono --> 16k stereo
				//>>>>>>>>>>>>>>>>>
				int out_byte_size = buf_len;
				in_frames = buf_len / (inputChannels * 16 / 8);
//				LOGD("_GeneralMicrophoneThread in_frames = %d .\n ",in_frames);
				if(inputSampleRate > 16000 )
				{
					out_frames = ((float)in_frames) / ((float)inputSampleRate/(float)16000);
				}else{
					out_frames = in_frames * (16000/inputSampleRate);
				}
//				LOGD("_GeneralMicrophoneThread out_frames = %d .\n ",out_frames);

				out_byte_size = out_frames * (inputChannels * 16 / 8);
//				LOGD("_GeneralMicrophoneThread out_byte_size = %d .\n ",out_byte_size);

	    		char out_byte_buffer [ out_byte_size ];
	    		memset(out_byte_buffer,0,out_byte_size);

				nice_resampler->resample_from_input(nice_resampler,
		                                   (int16_t *)mBuffer,
		                                   &in_frames,
		                                   (int16_t *)out_byte_buffer,
		                                   &out_frames);

				if( inputChannels == 2 )
				{
					send_mic_data(out_byte_buffer, out_byte_size);
				}else {
					int out_stereo_size = out_byte_size * 2;
					char out_stereo_buffer [ out_stereo_size ];
					memset(out_stereo_buffer, 0, out_stereo_size);
					for(int i=0; i<out_byte_size; i++)
					{
						if (i % 2 == 0)
						{
							memcpy(out_stereo_buffer + (2*i),   out_byte_buffer + i, 2);
							memcpy(out_stereo_buffer + (2*i+2), out_byte_buffer + i, 2);

						}
					}

	//				if(file != NULL && tinyplaySave == 1)
	//				{
	//					if (fwrite(out_stereo_buffer, sizeof(uint8_t), out_stereo_size, file) != out_stereo_size) {
	//						fprintf(stderr,"Error record microphone sample\n");
	//					}
	//				}
					send_mic_data(out_stereo_buffer, out_stereo_size);
				}
				//<<<<<<<<<<<<<<<<<
			}else {
				//16k  mono --> 48k stereo
				//>>>>>>>>>>>>>>>>>
				int out_byte_size = buf_len;
				in_frames = buf_len / (inputChannels * 16 / 8);
				out_frames = in_frames * (48000/inputSampleRate);
				out_byte_size = out_frames * (inputChannels * 16 / 8);

	    		char out_byte_buffer [ out_byte_size ];
	    		memset(out_byte_buffer,0,out_byte_size);

				nice_resampler->resample_from_input(nice_resampler,
		                                   (int16_t *)mBuffer,
		                                   &in_frames,
		                                   (int16_t *)out_byte_buffer,
		                                   &out_frames);

				if( inputChannels == 2 )
				{
					send_mic_data(out_byte_buffer, out_byte_size);
				}else {
					int out_stereo_size = out_byte_size * 2;
					char out_stereo_buffer [ out_stereo_size ];
					memset(out_stereo_buffer, 0, out_stereo_size);
					for(int i=0; i<out_byte_size; i++)
					{
						if (i % 2 == 0)
						{
							memcpy(out_stereo_buffer + (2*i),   out_byte_buffer + i, 2);
							memcpy(out_stereo_buffer + (2*i+2), out_byte_buffer + i, 2);

						}
					}

	//				if(file != NULL && tinyplaySave == 1)
	//				{
	//					if (fwrite(out_stereo_buffer, sizeof(uint8_t), out_stereo_size, file) != out_stereo_size) {
	//						fprintf(stderr,"Error record microphone sample\n");
	//					}
	//				}
					send_mic_data(out_stereo_buffer, out_stereo_size);
				}
				//<<<<<<<<<<<<<<<<<
			}
		}

	}
	//退出就绪
	__system_property_set("sys.lynx.txz.channel", "0");
	if( file != NULL )
	{
		fclose(file);
	}
	LOGD("_GeneralMicrophoneThread exit.\n ");
	return( NULL );
}

int tinyplay_set_parameter(int type,int sampleRate,int bits,int channels){
	inputChannels = channels;
	inputSampleRate = sampleRate;
	inputBits = bits;
	return 0;
}

int tinyplay_start(int type){
	LOGD("tinyplay_start  type = %d, inputSampleRate = %d, inputChannels = %d \n ",type,inputSampleRate,inputChannels);
    __system_property_get("ro.board.platform", board_platform);
    __system_property_get("sys.lynx.shark.dump_tinyplay", dump_tinyplay);
    __system_property_get("sys.lynx.bt.mt8163", bluetooth_call);
	if(strlen( dump_tinyplay ) > 0 )
	{
		tinyplaySave = atoi(dump_tinyplay);
	}
//	tinyplaySave = 1; //测试
	if(strlen( bluetooth_call ) > 0 )
	{
		mt8163_bluetooth_call = atoi(bluetooth_call);
	}

    if (strcmp(board_platform, "mt8163") == 0)
    {
    	mt8163_platform = 1;
    }
	if(AUDIO_CHANNEL_PHONE == type || AUDIO_CHANNEL_SPEECH == type)
	{
		if (nice_resampler) {
			release_resampler(nice_resampler);
			nice_resampler = NULL;
		}
		if (nice_resampler == NULL) {
			LOGD("__create_nice_resampler__inputSampleRate = %d \n",inputSampleRate);
			LOGD("__create_nice_resampler__inputChannels = %d \n",inputChannels);
			int targetSampleRate = 48000;
			if(mt8163_platform == 1 && mt8163_bluetooth_call == 1)
			{
				targetSampleRate = 16000;
			}
			int ret = create_resampler(inputSampleRate, targetSampleRate, inputChannels, 6, NULL, &nice_resampler);
			if (ret != 0) {
				LOGD("Create nice_resampler Failed \n");
				free(nice_resampler);
				nice_resampler = NULL;
			}
		}
	}
	volatile int				    err;
	err = pthread_create( &micAudioThread, NULL, _GeneralMicrophoneThread, NULL );
	if(err == 0)
	{
		micAudioThreadPtr = &micAudioThread;
	}
	return err;
}

int tinyplay_stop(int type){
	LOGD("tinyplay_stop type = %d .\n ",type);
	mic_capturing = 0;
	if( micAudioThreadPtr )
	{
		pthread_join( micAudioThread, NULL );
		micAudioThreadPtr = NULL;
	}
	if(AUDIO_CHANNEL_PHONE == type || AUDIO_CHANNEL_SPEECH == type)
	{
		if (nice_resampler) {
			LOGD("tinyplay_stop close release_nice_resampler .\n ");
			release_resampler(nice_resampler);
			nice_resampler = NULL;
		}

		if( mic_pcm != NULL )
		{
			LOGD("tinyplay_stop close pcm card .\n ");
			pcm_close(mic_pcm);
			mic_pcm = NULL;
		}
		xq_player_destroy(NULL);
	}
	LOGD("tinyplay_stop complete.\n ");
	return 0;
}

#if 0
int main(int argc, char **argv)
{
	unsigned int size = 16*16384;
    char *buffer = malloc(size);
    if (!buffer) {
        printf("Unable to allocate %d bytes\n", size);
        free(buffer);
    }
	memset(buffer, 1, size);
	while (1) {
	  send_mic_data(buffer, size);
	}
	return 0;
}
#endif
